class TestLog < ActiveRecord::Base
  belongs_to :test_base_data
  attr_accessible :SO_version, :algorithm_name, :algorithm_version, :device_model, :duration, :energy_used, :executed_at, :forecast_horizon, :forecasted_data, :memory_used

  def self.new_with_json! json
      test_log = TestLog.new({ :algorithm_name => json[:algorithmName],
                  :algorithm_version => json[:algorithmVersion],
                  :device_model => json[:deviceModel],
                  :SO_version => json[:SOVersion],
                  :executed_at => DateTime.parse(Time.at(json[:executedAt] / 1000).to_s), 
                  :forecast_horizon => json[:forecastHorizon],
                  :duration => json[:duration],
                  :memory_used => json[:memoryUsed],
                  :energy_used => json[:energyUsed],
                  :forecasted_data => Marshal.dump(json[:forecastedData])
      })
      test_base_data = TestBaseData.new_with_json json[:testBaseData]
      if test_base_data.save
        test_base_data.reload
        test_log.test_base_data_id = test_base_data.id
        return test_log
      else
        return nil
      end
  end
  
  def self.calc_duration_average test_logs
    sum = 0
    test_logs.each do |test_log|
      sum += test_log.duration
    end
    sum / test_logs.count
  end
  
  def self.calc_mem_use_average test_logs
    sum = 0
    test_logs.each do |test_log|
      sum += test_log.memory_used
    end
    sum / test_logs.count
  end
  
  def self.calc_energy_use_average test_logs
    sum = 0
    test_logs.each do |test_log|
      sum += test_log.energy_used
    end
    sum / test_logs.count
  end
  
  def self.calc_mae_average test_logs, horizon
    sum = 0
    test_logs.each do |test_log|
      sum += get_mean_absolute_error test_log, horizon
    end
    sum / test_logs.count
  end
  
  def self.calc_mape_average test_logs
    sum = 0
    test_logs.each do |test_log|
      sum += get_mean_absolute_percentage_error test_log
    end
    sum / test_logs.count
  end
  
  def self.get_mean_absolute_error test_log, horizon
    test_base_data = Marshal.load test_log.test_base_data.base_data
    forecasted_data = Marshal.load test_log.forecasted_data
    
    i = 0
    e_sum = 0
    while i < horizon.to_i
      e_sum += (test_base_data[test_base_data.count - test_log.forecast_horizon + i] - forecasted_data[i]).abs
      i+=1
    end
    
    mae = e_sum.to_d/horizon.to_d
  end
  
  def self.get_mean_absolute_percentage_error test_log
    test_base_data = Marshal.load test_log.test_base_data.base_data
    forecasted_data = Marshal.load test_log.forecasted_data
    
    percent_sum = 0
    forecasted_data.each_with_index do |forecasted_value, index|
      test_base_value = test_base_data[test_base_data.count - test_log.forecast_horizon + index]
      percent_sum += ((test_base_value.to_d - forecasted_value.to_d)/test_base_value.to_d).abs
    end
    
    mape = (percent_sum.to_d/test_log.forecast_horizon.to_d)*100.0
  end
end
